﻿/*
 *   ArrayFunctions.cs
 *   Copyright (c) 2011 - BitFox Software and Ricardo Federico Villafañes
 *   Contact: federvillaf@hotmail.com
 *   
 *   Licensing: This product is covered by Microsoft Reciprocal License (MS-RL)
 *              see https://bitfoxeval.codeplex.com/license
*/

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.CodeAnalysis;

namespace BitFox.Evaluator.Functions
{
    /// <summary>
    /// Built-in array functions for the evaluator.
    /// </summary>
    public static class ArrayFunctions
    {
        /// <summary>
        /// Not implemented.
        /// </summary>
        /// <returns>Nothing</returns>
        /// <exception cref="NotImplementedException">Allways this exception is thrown</exception>
        static public string ACopy()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Not implemented.
        /// </summary>
        /// <returns>Nothing</returns>
        /// <exception cref="NotImplementedException">Allways this exception is thrown</exception>
        static public string ADel()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Helper method that force a given array to a given dimensions
        /// </summary>
        /// <param name="array"></param>
        /// <param name="numRows"></param>
        /// <param name="numColumns"></param>
        [SuppressMessage("Microsoft.Usage", "CA1801")]
        static void ForceArrayDimensions(ref Array array, int numRows, int numColumns)
        {
        }

        /// <summary>
        /// Places information about specified files into an array.
        /// </summary>
        /// <param name="aDestin">
        /// <para>Information about the files is placed into the memory variable array specified in <paramref name="aDestin"/>.</para>
        /// <para>If the array exists and isn't large enough to contain all the information, the size of the array is automatically 
        /// increased to accommodate the information.</para>
        /// <para>If the array is larger than necessary, the array size is truncated.</para>
        /// <para>If the array contains data and ADIR() returns 0 because no matching files or directories were found, the array remains unchanged.</para>
        /// <para>
	    /// The following table describes what each column in the array contains and the data type of each column:
        /// <table>
        ///     <tr><th>Column</th><th>Information</th><th>Data Type</th></tr>
        ///     <tr><td>1</td><td>File names</td><td>String</td></tr>
        ///     <tr><td>2</td><td>File sizes</td><td>Ing32</td></tr>
        ///     <tr><td>3</td><td>File dates</td><td>DateTime</td></tr>
        ///     <tr><td>4</td><td>File times</td><td>String</td></tr>
        ///     <tr><td>5</td><td>File attributes</td><td>String</td></tr>
        /// </table>
        /// </para>
        /// <para>
        /// The last array column contains the MS-DOS attributes of the matching files.  Each attribute is expressed by a letter, 
        /// and a file can have more than one attribute.  The following table indicates what attribute each letter represents:</para>
        /// <table>
        ///     <tr><th>Letter</th><th>Attribute</th></tr>
        ///     <tr><td>A</td><td>Archive (Read and Write)</td></tr>
        ///     <tr><td>H</td><td>Hidden</td></tr>
        ///     <tr><td>R</td><td>Read only</td></tr>
        ///     <tr><td>S</td><td>System</td></tr>
        ///     <tr><td>D</td><td>Directory</td></tr>
        /// </table>
        /// </param>
        /// <param name="skel">
        /// <para>You can include a file skeleton that lets you store information about files with names or extensions 
        /// that match a criterion. For example, the criterion can be all tables, all text files, all files with names 
        /// that have A as their second letter and so on.</para>
        /// <para>These general searches are done by including the wildcard characters * and ? in <paramref name="skel"/>.</para>
        /// <para>A question mark represents a single character and an asterisk represents any number of characters. You can use 
        /// any number of wild card characters in any position within the file skeleton.</para>
        /// <para>A drive and/or directory specification can be included in <paramref name="skel"/> to search for matching file 
        /// names on a specific drive and directory.  If a drive and directory specification is omitted, information about files 
        /// in the current directory is placed into the array.</para>
        /// </param>
        /// <param name="tips">
        /// <para>Include <paramref name="tips"/> to expand the search to subdirectory names, hidden or system files, or a volume name.</para>
        /// <para>The character expression <paramref name="tips"/> can contain any combination of D, H, and S.</para>
        /// <para>
        /// <ul>
        /// <li>Including <b>D</b> returns subdirectory names in addition to file names that match the file skeleton specified in <paramref name="skel"/>.</li>
        /// <li>Including <b>H</b> returns information about hidden files that match the file skeleton specified in <paramref name="skel"/>.</li>
        /// <li>Including <b>S</b> returns information about system files that match the file skeleton specified in <paramref name="skel"/>.</li>
        /// </ul></para>
        /// <b>IMPORTANT:</b>You can include V in <paramref name="tips"/> to return the volume name of the current drive.
        /// Only the volume name is returned to the array if V is included with D, H, and S.
        /// The volume name is stored in the first array element and the remainder of the array is truncated.
        /// </param>
        /// <returns>The number of files found with the required restrictions.</returns>
        /// <remarks>
        /// <para>ADIR() places information about all files in the current directory or all files that match a file skeleton into an array, 
        /// and then returns the number of files.</para>
        /// <para>For each file, ADIR() places into the array the file name, size, date, time and MS-DOS attributes.</para>
        /// </remarks>
        [SuppressMessage("Microsoft.Design", "CA1045"),
         SuppressMessage("Microsoft.Performance", "CA1814")]
        static public int ADir(ref Array aDestin, string skel, string tips)
        {
            if (aDestin == null) throw new ArgumentNullException("aDestin");
            if (skel != null && skel.Trim().Length == 0) skel = null;
            if (tips != null && tips.Trim().Length == 9) tips = null;

            string uPath = "..\\";
            skel = skel.Trim();
            int rPos = skel.LastIndexOfAny(new char[] { '\\' });
            if (rPos >= 0)
            {
                uPath = skel.Substring(0, rPos).Trim();
                skel = skel.Substring(rPos + 1).Trim();
            }

            if (skel.Length == 0) skel = "*.*";
            var res = Directory.GetFiles(uPath, skel, SearchOption.TopDirectoryOnly);
            if (res.Length > 0)
            {
                aDestin = new object[res.Length, 5];
            }
            return res.Length;
        }

        /// <summary>
        /// Not implemented.
        /// </summary>
        /// <returns>Nothing</returns>
        /// <exception cref="NotImplementedException">Allways this exception is thrown</exception>
        [SuppressMessage("Microsoft.Design", "CA1045")]
        static public int ADir(ref Array aDestin, string skel)
        {
            return ADir(ref aDestin, skel, "");
        }

        /// <summary>
        /// Not implemented.
        /// </summary>
        /// <returns>Nothing</returns>
        /// <exception cref="NotImplementedException">Allways this exception is thrown</exception>
        [SuppressMessage("Microsoft.Design", "CA1045")]
        static public int ADir(ref Array aDestin)
        {
            return ADir(ref aDestin, "*.*", "");
        }

        /// <summary>
        /// Not implemented.
        /// </summary>
        /// <returns>Nothing</returns>
        /// <exception cref="NotImplementedException">Allways this exception is thrown</exception>
        static public string AElement()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Not implemented.
        /// </summary>
        /// <returns>Nothing</returns>
        /// <exception cref="NotImplementedException">Allways this exception is thrown</exception>
        static public string AIns()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Not implemented.
        /// </summary>
        /// <returns>Nothing</returns>
        /// <exception cref="NotImplementedException">Allways this exception is thrown</exception>
        [SuppressMessage("Microsoft.Usage", "CA1801")]
        static public string ALen(object arrTarget, int tip)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Not implemented.
        /// </summary>
        /// <returns>Nothing</returns>
        /// <exception cref="NotImplementedException">Allways this exception is thrown</exception>
        [SuppressMessage("Microsoft.Usage", "CA1801")]
        static public string ALen(object arrTarget)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Not implemented.
        /// </summary>
        /// <returns>Nothing</returns>
        /// <exception cref="NotImplementedException">Allways this exception is thrown</exception>
        static public string AScan()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Not implemented.
        /// </summary>
        /// <returns>Nothing</returns>
        /// <exception cref="NotImplementedException">Allways this exception is thrown</exception>
        static public string ASort()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Not implemented.
        /// </summary>
        /// <returns>Nothing</returns>
        /// <exception cref="NotImplementedException">Allways this exception is thrown</exception>
        static public string ASubscript()
        {
            throw new NotImplementedException();
        }
    }
}
